package cn.getech.data.metadata.service.impl;

import cn.getech.data.development.api.DefaultSecurityDataApi;
import cn.getech.data.development.entity.ConfConnect;
import cn.getech.data.development.service.ConfConnectService;
import cn.getech.data.development.utils.SendEMailUtil;
import cn.getech.data.development.vo.SecurityLevelVO;
import cn.getech.data.intelligence.common.exception.RRException;
import cn.getech.data.intelligence.common.utils.PageUtils;
import cn.getech.data.intelligence.common.utils.Query;
import cn.getech.data.metadata.constant.ConnectTypeEnum;
import cn.getech.data.metadata.constant.LogTypeEnum;
import cn.getech.data.metadata.constant.TaskStatusEnum;
import cn.getech.data.metadata.constant.YesOrNoEnum;
import cn.getech.data.metadata.controller.module.ModuleUtils;
import cn.getech.data.metadata.entity.*;
import cn.getech.data.metadata.entity.meta.*;
import cn.getech.data.metadata.mapper.*;
import cn.getech.data.metadata.model.excel.CollectionTableFieldExcel;
import cn.getech.data.metadata.model.req.meta.CollectionTaskListReq;
import cn.getech.data.metadata.model.res.CollectionTaskDetail;
import cn.getech.data.metadata.service.*;
import cn.getech.data.metadata.utils.MapUtils;
import cn.getech.data.metadata.utils.SendEmailDelayUtil;
import cn.getech.data.metadata.utils.TableHtmlUtil;
import cn.getech.system.center.entity.SysRoleEntity;
import cn.getech.system.center.entity.SysTenant;
import cn.getech.system.center.entity.SysUserEntity;
import cn.getech.system.center.model.res.UserListRes;
import cn.getech.system.center.service.SysRoleService;
import cn.getech.system.center.service.SysTenantService;
import cn.getech.system.center.service.SysUserService;
import cn.getech.system.center.utils.ShiroUtils;
import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Maps;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.ObjectUtils;
import org.apache.commons.lang.StringUtils;
import org.elasticsearch.action.bulk.BulkRequest;
import org.elasticsearch.action.bulk.BulkResponse;
import org.elasticsearch.action.delete.DeleteRequest;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.io.IOException;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneId;
import java.util.*;
import java.util.stream.Collectors;

import static cn.getech.data.development.service.impl.TableInfoServiceImpl.distinctByKey;

@Slf4j
@Service
public class CollectionTaskServiceImpl extends ServiceImpl<CollectionTaskMapper, CollectionTask> implements CollectionTaskService {
    @Autowired
    private SysUserService sysUserService;
    @Autowired
    private SysTenantService sysTenantService;
    @Autowired
    private CollectionSystemModuleMapper collectionSystemModuleMapper;
    @Autowired
    private CollectionTableInfoMapper collectionTableInfoMapper;
    @Autowired
    private CollectionTableFieldMapper collectionTableFieldMapper;
    @Autowired
    private CollectionTableFieldLogMapper collectionTableFieldLogMapper;
    @Autowired
    private CollectionTaskLogMapper collectionTaskLogMapper;
    @Autowired
    private CollectionTableOperateService collectionTableOperateService;
    @Autowired
    private CollectionRunLogMapper collectionRunLogMapper;
    @Autowired
    private CollectionTableChangeNotifyService collectionTableChangeNotifyService;
    @Autowired
    private CollectionTableInfoService collectionTableInfoService;
    @Autowired
    private CollectionTableUserNotifyService collectionTableUserNotifyService;
    @Autowired
    private CollectionTaskScheduleConfigService collectionTaskScheduleConfigService;
    @Autowired
    private ConfConnectService confConnectService;
    @Autowired
    private CollectionSystemModuleService collectionSystemModuleService;
    @Autowired
    private SysRoleService sysRoleService;

    @Autowired
    private DefaultSecurityDataApi defaultSecurityDataApi;
    @Autowired
    private CollectionNotificationRelatednessUserService collectionNotificationRelatednessUserService;
    @Autowired
    private CollectionNotificationReceivedService collectionNotificationReceivedService;
    @Autowired
    private CollectionNotificationHistoryService collectionNotificationHistoryService;
    @Autowired
    private SendEMailUtil sendEMailUtil;
    @Autowired
    private CollectionTaskCategoryMapper collectionTaskCategoryMapper;

    private void addTable(Date now, CollectionTask task, String tableLeader,
                          Long userId, List<CollectionTableInfo> tableAddList,
                          CollectionTableInfo table,
                          List<CollectionTableFieldExcel> fieldList,
                          List<CollectionTableField> fieldAddList,
                          Boolean check) {
        table.setCreateTime(now);
        table.setTaskType(YesOrNoEnum.NO.getValue());
        table.setTableLeader(tableLeader);
        table.setCreateUser(userId);
        table.setUpdateUser(userId);
        table.setOwnModule(task.getOwnModule());
        table.setOwnSystem(task.getOwnSystem());
        table.setUpdateTime(now);
        table.setTableType(3);//外部元数据
        table.setSourceId(-1);//其他数据源
        if(table.getRowsNum()==null){
            table.setRowsNum(0L);
        }
        if(table.getTotalSize()==null){
            table.setTotalSize(0d);
        }
//        table.setEnableChangeNotify(YesOrNoEnum.NO.getValue());//是否开启变更通知 0:关闭 1:开启
        tableAddList.add(table);
        if (!check) {//校验时候  不插入数据
            collectionTableInfoMapper.insertOrUpdateSelective(table);
        }
        for (CollectionTableFieldExcel collectionTableFieldExcel : fieldList) {
            CollectionTableField field = collectionTableFieldExcel.toField(table.getId(), null);
            field.setFieldOrder(collectionTableFieldExcel.getOrder());
            field.setCreateTime(now);
            field.setCreateUser(userId);
            field.setUpdateTime(now);
            field.setUpdateUser(userId);
            //导入的表没有分区和主键两个值
            if(field.getIsPartition()==null){
                field.setIsPartition(0);
            }
            field.setPrimaryKey(0);
            fieldAddList.add(field);
        }
    }

    private void updateTable(List<CollectionTableInfo> noneTableList, Integer exportType, Date now,
                             Map<Integer, List<CollectionTableField>> allFieldListMap,
                             CollectionTableInfo table,
                             List<CollectionTableInfo> tableUpdateList,
                             List<CollectionTableFieldExcel> newExcelFieldList,
                             List<CollectionTableField> fieldUpdateList,
                             List<CollectionTableField> fieldDeleteList,
                             List<CollectionTableField> fieldAddList,
                             Long userId) {
        table.setSourceId(-1);//其他数据源
        table.setUpdateUser(userId);
        table.setTableType(3);//外部元数据
        table.setUpdateTime(now);
        List<CollectionTableField> oldFieldList = allFieldListMap.get(table.getId());
        HashMap<String, CollectionTableField> oldFieldListMap = Maps.newHashMap();
        HashMap<String, CollectionTableField> newFieldListMap = Maps.newHashMap();
        if (CollectionUtils.isNotEmpty(oldFieldList)) {
            for (CollectionTableField field : oldFieldList) {
                oldFieldListMap.put(field.getFieldName(), field);
            }
        }
        boolean isUpdate = false;
        for (CollectionTableFieldExcel collectionTableFieldExcel : newExcelFieldList) {
            CollectionTableField old = oldFieldListMap.get(collectionTableFieldExcel.getFieldName());
            CollectionTableField field = collectionTableFieldExcel.toField(table.getId(), old);
            field.setUpdateTime(now);
            field.setUpdateUser(userId);
            if (field.getId() != null && collectionTableFieldExcel.isChangeFlag()) {
                fieldUpdateList.add(field);
                isUpdate = true;
            } else if (field.getId() == null) {
                field.setCreateTime(now);
                field.setCreateUser(userId);
                fieldAddList.add(field);
                isUpdate = true;
            }
            newFieldListMap.put(field.getFieldName(), field);
        }
        if (YesOrNoEnum.YES.getValue().equals(exportType)) {//全量
            for (String s : oldFieldListMap.keySet()) {
                if (!newFieldListMap.keySet().contains(s)) {
                    fieldDeleteList.add(oldFieldListMap.get(s));
                    isUpdate = true;
                }
            }
        }
        if (isUpdate) {
            tableUpdateList.add(table);
        } else {
            noneTableList.add(table);
        }
    }

    private void addTableOperate(List<CollectionTableInfo> tableAddList,
                                 List<CollectionTableInfo> tableUpdateList,
                                 Long taskLogId) {
        Long userId = ShiroUtils.getUserId();
        //表信息修改更新时间
        List<Integer> tableIdList = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(tableUpdateList)) {
            for (CollectionTableInfo tableInfo : tableUpdateList) {
                tableIdList.add(tableInfo.getId());
            }
        }

        tableAddList.addAll(tableUpdateList);

        //添加表结构操作审计
        List<CollectionTableOperateEntity> saveList = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(tableAddList)) {
            for (CollectionTableInfo tableInfo : tableAddList) {
                CollectionTableOperateEntity operateEntity = new CollectionTableOperateEntity();
                operateEntity.setTableId(tableInfo.getId());
                operateEntity.setOperateType(1); //1:表结构 2:表属性
                operateEntity.setOperateType1Res(taskLogId);
                operateEntity.setOperateType2Res("");
                operateEntity.setUserId(userId);
                operateEntity.setOperateTime(new Date());
                if(!saveList.contains(operateEntity))
                    saveList.add(operateEntity);
            }
        }

        if (CollectionUtils.isNotEmpty(tableUpdateList)) {
            for (CollectionTableInfo tableInfo : tableUpdateList) {
                CollectionTableOperateEntity operateEntity = new CollectionTableOperateEntity();
                operateEntity.setTableId(tableInfo.getId());
                operateEntity.setOperateType(1); //1:表结构 2:表属性
                operateEntity.setOperateType1Res(taskLogId);
                operateEntity.setOperateType2Res("");
                operateEntity.setUserId(userId);
                operateEntity.setOperateTime(new Date());
                if(!saveList.contains(operateEntity))
                    saveList.add(operateEntity);
            }
        }

        if (CollectionUtil.isNotEmpty(saveList)) {
            collectionTableOperateService.saveBatch(saveList);
        }
        if (CollectionUtil.isNotEmpty(tableIdList)) {
            collectionTableInfoMapper.updateTimeBatch(tableIdList);
        }
        //collectionTableOperateService.save(operateEntity);
    }

    private void insertTaskLog(
            Long logId,
            List<CollectionTableInfo> noneTableList,
            List<CollectionTableInfo> tableAddList,
            List<CollectionTableInfo> tableUpdateList,
            List<CollectionTableInfo> tableDeleteList,
            List<CollectionTableField> fieldAddList,
            List<CollectionTableField> fieldUpdateList,
            List<CollectionTableField> fieldDeleteList) {

        List<CollectionTableFieldLog> logList = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(noneTableList)) {
            for (CollectionTableInfo tableInfo : noneTableList) {
                CollectionTableFieldLog log = new CollectionTableFieldLog(
                        logId, tableInfo.getId(),
                        null, YesOrNoEnum.NO.getValue(),
                        LogTypeEnum.NONE.getValue(), null);
                logList.add(log);
            }
        }
        if (CollectionUtils.isNotEmpty(tableAddList)) {
            for (CollectionTableInfo tableInfo : tableAddList) {
                CollectionTableFieldLog log = new CollectionTableFieldLog(
                        logId, tableInfo.getId(),
                        null, YesOrNoEnum.NO.getValue(),
                        LogTypeEnum.ADD.getValue(), null);
                logList.add(log);
            }
        }
        if (CollectionUtils.isNotEmpty(tableUpdateList)) {
            for (CollectionTableInfo tableInfo : tableUpdateList) {
                CollectionTableFieldLog log = new CollectionTableFieldLog(
                        logId, tableInfo.getId(),
                        null, YesOrNoEnum.NO.getValue(),
                        LogTypeEnum.UPDATE.getValue(), null);
                logList.add(log);
            }
        }
        if (CollectionUtils.isNotEmpty(tableDeleteList)) {
            for (CollectionTableInfo tableInfo : tableDeleteList) {
                CollectionTableFieldLog log = new CollectionTableFieldLog(
                        logId, tableInfo.getId(),
                        null, YesOrNoEnum.NO.getValue(),
                        LogTypeEnum.DELETE.getValue(), null);
                logList.add(log);
            }
        }
        if (CollectionUtils.isNotEmpty(fieldAddList)) {
            for (CollectionTableField field : fieldAddList) {
                CollectionTableFieldLog log = new CollectionTableFieldLog(
                        logId, field.getTableId(),
                        field.getId(), YesOrNoEnum.YES.getValue(),
                        LogTypeEnum.ADD.getValue(), null);
                logList.add(log);
            }
        }
        if (CollectionUtils.isNotEmpty(fieldUpdateList)) {
            for (CollectionTableField field : fieldUpdateList) {
                CollectionTableFieldLog log = new CollectionTableFieldLog(
                        logId, field.getTableId(),
                        field.getId(), YesOrNoEnum.YES.getValue(),
                        LogTypeEnum.UPDATE.getValue(), field.getChangeInfo());
                logList.add(log);
            }
        }
        if (CollectionUtils.isNotEmpty(fieldDeleteList)) {
            for (CollectionTableField field : fieldDeleteList) {
                CollectionTableFieldLog log = new CollectionTableFieldLog(
                        logId, field.getTableId(),
                        field.getId(), YesOrNoEnum.YES.getValue(),
                        LogTypeEnum.DELETE.getValue(), null);
                logList.add(log);
            }
        }
        if (CollectionUtil.isNotEmpty(logList)) {
            collectionTableFieldLogMapper.batchInsert(logList);
        }
        addTableOperate(tableAddList, tableUpdateList, logId);
    }

    @Transactional
    @Override
    public JSONObject saveTableField(Long start, Long taskId, List<CollectionTableFieldExcel> list, Boolean check) {

        Date now = new Date();
        Long userId = ShiroUtils.getUserId();
        Integer tenantId = ShiroUtils.getTenantId();
        String logContent = "";
        Map<String, List<CollectionTableFieldExcel>> mapList = list.stream()
                .collect(Collectors.groupingBy(CollectionTableFieldExcel::getUniqueTable));
        CollectionTask task = baseMapper.selectById(taskId);
        QueryWrapper<CollectionTableInfo> param = new QueryWrapper<>();
        param.eq("own_module", task.getOwnModule())
                .eq("delete_flag", YesOrNoEnum.NO.getValue())
                .eq("tenant_id", tenantId);
        List<CollectionTableInfo> allTableList = collectionTableInfoMapper.selectList(param);
        Map<String, CollectionTableInfo> allTableMap = Maps.newHashMap();
        Map<Integer, List<CollectionTableField>> allFieldListMap = Maps.newHashMap();
        if (CollectionUtils.isNotEmpty(allTableList)) {
            List<Integer> tableIds = new ArrayList<>(allTableList.size());
            for (CollectionTableInfo collectionTableInfo : allTableList) {
                allTableMap.put(collectionTableInfo.getDbName() + "_" + collectionTableInfo.getTableName()
                        , collectionTableInfo);
                tableIds.add(collectionTableInfo.getId());
            }
            List<CollectionTableField> allFieldList = collectionTableFieldMapper.selectList(
                    new QueryWrapper<CollectionTableField>()
                            .in("table_id", tableIds)
                            .eq("delete_flag", YesOrNoEnum.NO.getValue()));
            allFieldListMap = allFieldList.stream()
                    .collect(Collectors.groupingBy(CollectionTableField::getTableId));
        }
        List<CollectionTableInfo> tableAddList = new ArrayList<>();
        List<CollectionTableInfo> tableUpdateList = new ArrayList<>();
        List<CollectionTableInfo> tableDeleteList = new ArrayList<>();
        List<CollectionTableInfo> noneTableList = new ArrayList<>();//变化表
        List<CollectionTableField> fieldAddList = new ArrayList<>();
        List<CollectionTableField> fieldUpdateList = new ArrayList<>();
        List<CollectionTableField> fieldDeleteList = new ArrayList<>();
        SecurityLevelVO securityLevelVO= defaultSecurityDataApi.getDefaultSecurityDataLevel();
        if (YesOrNoEnum.YES.getValue().equals(task.getExportType())) {//全量
            for (String uniqueTable : allTableMap.keySet()) {
                if (!mapList.keySet().contains(uniqueTable)) {
                    tableDeleteList.add(allTableMap.get(uniqueTable));
                } else {
                    CollectionTableInfo table = mapList.get(uniqueTable).get(0)
                            .toToTable(allTableMap.get(uniqueTable));
                    List<CollectionTableFieldExcel> fieldList = mapList.get(uniqueTable);
                    updateTable(noneTableList, task.getExportType(), now, allFieldListMap, table, tableUpdateList, fieldList,
                            fieldUpdateList, fieldDeleteList, fieldAddList, userId);
                }
            }
            for (String uniqueTable : mapList.keySet()) {
                if (!allTableMap.keySet().contains(uniqueTable)) {//新增的
                    CollectionTableInfo table = mapList.get(uniqueTable).get(0).toToTable(null);
                    List<CollectionTableFieldExcel> fieldList = mapList.get(uniqueTable);
                    setTableDefaultSecrityData(table,securityLevelVO);
                    table.setTenantId(tenantId);
                    addTable(now, task, null, userId, tableAddList,
                            table, fieldList, fieldAddList, check);
                }
            }
        } else { //增量
            for (String uniqueTable : mapList.keySet()) {
                if (allTableMap.keySet().contains(uniqueTable)) {//修改的表
                    CollectionTableInfo table = mapList.get(uniqueTable).get(0)
                            .toToTable(allTableMap.get(uniqueTable));
                    List<CollectionTableFieldExcel> fieldList = mapList.get(uniqueTable);
                    updateTable(noneTableList, task.getExportType(), now, allFieldListMap, table, tableUpdateList, fieldList,
                            fieldUpdateList, fieldDeleteList, fieldAddList, userId);
                } else {//新增的表
                    CollectionTableInfo table = mapList.get(uniqueTable).get(0).toToTable(null);
                    setTableDefaultSecrityData(table,securityLevelVO);
                    List<CollectionTableFieldExcel> fieldList = mapList.get(uniqueTable);
                    table.setTenantId(tenantId);
                    addTable(now, task, null, userId, tableAddList, table, fieldList, fieldAddList, check);
                }
            }
        }
        if (check) {//校验文件
            JSONObject data = new JSONObject();
            data.put("allTableList", allTableList);
            data.put("noneTableList", noneTableList);
            data.put("tableUpdateList", tableUpdateList);
            data.put("tableDeleteList", tableDeleteList);
            data.put("tableAddList", tableAddList);
            data.put("fieldAddList", fieldAddList);
            data.put("fieldUpdateList", fieldUpdateList);
            data.put("fieldDeleteList", fieldDeleteList);
            return data;
        } else {
            /**
             * 本次成功采集1000张表：
             *  新增100张表
             *  修改100张表（修改字段名称、类型、描述、是否分区字段）
             *  无变化100张表
             *  删除10张表
             */
            int total = mapList.keySet().size();
            logContent += "本次成功采集" + total + "张表\n";
            logContent += "新增" + tableAddList.size() + "张表\n";
            logContent += "修改" + tableUpdateList.size() + "张表\n";
            logContent += "无变化" + noneTableList.size() + "张表\n";
            logContent += "删除" + tableDeleteList.size() + "张表\n";

            if (CollectionUtils.isNotEmpty(tableUpdateList)) {
                collectionTableInfoMapper.updateBatch(tableUpdateList);
            }
            if (CollectionUtils.isNotEmpty(noneTableList)) {
                collectionTableInfoMapper.updateBatch(noneTableList);
            }
            if (CollectionUtils.isNotEmpty(tableDeleteList)) {
                collectionTableInfoMapper.deleteBatch(tableDeleteList.stream()
                        .map(CollectionTableInfo::getId).collect(Collectors.toList()));
            }
            if (CollectionUtils.isNotEmpty(fieldAddList)) {
                setFieldDefaultSecrityData(fieldAddList,securityLevelVO);
                collectionTableFieldMapper.batchInsert(fieldAddList);
                logContent += "新增字段的个数为" + fieldAddList.size() + "\n";
            }
            if (CollectionUtils.isNotEmpty(fieldUpdateList)) {
                setFieldDefaultSecrityData(fieldUpdateList,securityLevelVO);
                collectionTableFieldMapper.updateBatch(fieldUpdateList);
                logContent += "修改字段的个数为" + fieldAddList.size() + "\n";
            }
            if (CollectionUtils.isNotEmpty(fieldDeleteList)) {
                collectionTableFieldMapper.removeBatchIds(fieldDeleteList
                        .stream().map(CollectionTableField::getId).collect(Collectors.toList()));
                logContent += "删除字段的个数为" + fieldDeleteList.size() + "\n";
            }
            //结束时间
            task.setRunCount(task.getRunCount() + 1);
            task.setRunStatus(TaskStatusEnum.SUCCESS.getValue());
            Long logId = insertRunLog(start, task, logContent);
            insertTaskLog(logId, noneTableList, tableAddList, tableUpdateList, tableDeleteList,
                    fieldAddList, fieldUpdateList, fieldDeleteList);
            baseMapper.updateById(task);
              //表变更通知列表
            List<CollectionTableChangeNotifyEntity> notifyList = new ArrayList<>();
            addChangeNotify(tableUpdateList, tableDeleteList, logId, task.getId(), notifyList);

            List<CollectionTableInfo> tableAllList = new ArrayList<>();
            tableAllList.addAll(tableAddList);
            tableAllList.addAll(tableUpdateList);
            tableAllList.addAll(noneTableList);
            //添加初始化权限
            collectionTableInfoService.saveMetaPermission(tableAllList,task.getInitRole(), tableDeleteList, userId);
            //发送变更邮件
            sendEmailFeignApi(tableAddList,tableUpdateList,tableDeleteList,fieldAddList,fieldUpdateList,fieldDeleteList,task);
        }
        return null;
    }

    private void addChangeNotify(List<CollectionTableInfo> tableUpdateList, List<CollectionTableInfo> tableDeleteList,
                                 Long logId, Long taskId, List<CollectionTableChangeNotifyEntity> notifyList) {
        addChangeNotify(tableUpdateList, logId, taskId, notifyList);

        addChangeNotify(tableDeleteList, logId, taskId, notifyList);

        if (CollectionUtil.isNotEmpty(notifyList)) {
            collectionTableChangeNotifyService.saveBatch(notifyList);
        }
    }

    private void addChangeNotify(List<CollectionTableInfo> updateDeleteList,
                                 Long logId, Long taskId, List<CollectionTableChangeNotifyEntity> notifyList) {
        for (CollectionTableInfo tableInfo : updateDeleteList) {
            //判断是否开启变更通知
            boolean isAdd = false;
            int count = collectionTableUserNotifyService.count(
                    new QueryWrapper<CollectionTableUserNotifyEntity>()
                            .eq("table_id", tableInfo.getId())
            );
            if(count > 0)
                isAdd = true;

            if (isAdd) {
                CollectionTableChangeNotifyEntity notifyEntity = new CollectionTableChangeNotifyEntity();
                notifyEntity.setTableId(tableInfo.getId());
                notifyEntity.setTaskId(taskId);
                notifyEntity.setTaskLogId(logId);
                notifyEntity.setCreateTime(new Date());
                notifyList.add(notifyEntity);
            }
        }

    }

    @Override
    public JSONObject getCheckExcel(Long taskId, List<CollectionTableFieldExcel> list) {
        return saveTableField(null, taskId, list, true);
    }

    @Override
    public Long insertRunLog(Long start, CollectionTask task, String logContent) {
        return insertRunLog(start, task, logContent, ShiroUtils.getUserId());
    }

    @Override
    public Long insertRunLog(Long start, CollectionTask task, String logContent, Long userId) {
        CollectionTaskLog taskLog = new CollectionTaskLog();
        BeanUtils.copyProperties(task, taskLog);
        taskLog.setTaskId(task.getId());
        Long end = System.currentTimeMillis();
        taskLog.setConsumerSeconds((end - start));
        taskLog.preSave(userId);
        collectionTaskLogMapper.insert(taskLog);
        CollectionRunLog logRun = new CollectionRunLog();
        logRun.setLogContent(logContent);
        logRun.setLogId(taskLog.getId());
        collectionRunLogMapper.insertOrUpdate(logRun);
        return taskLog.getId();
    }

    @Override
    public Long insertRunLog(CollectionTaskLog taskLog, String logContent) {
        collectionTaskLogMapper.insert(taskLog);
        CollectionRunLog logRun = new CollectionRunLog();
        logRun.setLogContent(logContent);
        logRun.setLogId(taskLog.getId());
        collectionRunLogMapper.insertOrUpdate(logRun);
        return taskLog.getId();
    }

    @Override
    public void saveTask(CollectionTask collectionTask,List<Long> userGroup) {
        Long userId = ShiroUtils.getUserId();
        Integer tenantId = ShiroUtils.getTenantId();
        collectionTask.setTenantId(tenantId);
        collectionTask.preSave(userId);
        //元数据所属 改成 资产类目
        CollectionSystemModuleEntity moduleEntity = collectionSystemModuleMapper
                .selectById(collectionTask.getOwnModule());
        if (moduleEntity != null) {
            collectionTask.setOwnModuleLeader(moduleEntity.getManager());
        }else {
            collectionTask.setOwnModule(-2);
        }
        if (YesOrNoEnum.NO.getValue().equals(collectionTask.getTaskType())) {
            collectionTask.setRunPlan("按需采集");
        }
        if (collectionTask.getId() == null) {//新增任务时候
            List<CollectionTask> list = baseMapper.selectList(
                    new QueryWrapper<CollectionTask>()
                            .eq("task_name", collectionTask.getTaskName())
                            .eq(tenantId != null, "tenant_id", tenantId)
                            .eq("delete_flag", YesOrNoEnum.NO.getValue()));
            if (CollectionUtil.isNotEmpty(list)) {
                throw new RRException(collectionTask.getTaskName() + ",任务已经存在");
            }
        } else {
            CollectionTask task = baseMapper.selectById(collectionTask.getId());
            if (task.getRunStatus().equals(TaskStatusEnum.RUNNING.getValue())) {
                throw new RRException(collectionTask.getTaskName() + ",运行中,不可以修改");
            }
        }
        baseMapper.insertOrUpdateSelective(collectionTask);
        //先删掉旧的关系
        collectionTaskCategoryMapper.delete(new QueryWrapper<CollectionTaskCategory>()
                .eq("task_id",collectionTask.getId())
                .eq("tenant_id",ShiroUtils.getTenantId()));
        //再添加新的关系
        if(CollectionUtil.isNotEmpty(collectionTask.getCategoryIdsList())){
            for(String categoryId:collectionTask.getCategoryIdsList()){
                Integer id = Integer.valueOf(categoryId);
                CollectionTaskCategory category = new CollectionTaskCategory();
                category.setCategoryId(id);
                category.setTaskId(collectionTask.getId().intValue());
                category.setCreateId(ShiroUtils.getUserId().intValue());
                category.setCreateTime(new Date());
                category.setTenantId(ShiroUtils.getTenantId());
                collectionTaskCategoryMapper.insert(category);
            }
        }
        //新增时关联用户组通知
        if (collectionTask.getId() == null) {
            if(CollectionUtil.isNotEmpty(userGroup)){
                for(Long userGroupId:userGroup){
                    CollectionNotificationRelatednessUser collectionNotificationRelatednessUser = new CollectionNotificationRelatednessUser();
                    collectionNotificationRelatednessUser.setUpdateTime(new Date());
                    collectionNotificationRelatednessUser.setCreateTime(new Date());
                    collectionNotificationRelatednessUser.setCollectionNotificationUserId(userGroupId);
                    collectionNotificationRelatednessUser.setCollectionRelatednessId(collectionTask.getId());
                    collectionNotificationRelatednessUser.setRelatednessType("1");
                    collectionNotificationRelatednessUser.setUpdateUser(ShiroUtils.getUserId());
                    collectionNotificationRelatednessUser.setCreateUser(ShiroUtils.getUserId());
                    collectionNotificationRelatednessUserService.saveRelatednessNotification(collectionNotificationRelatednessUser);
                }
            }
        //编辑时关联用户组
        }else{
            if(CollectionUtil.isNotEmpty(userGroup)){
                ArrayList<CollectionNotificationRelatednessUser> collectionNotificationRelatednessUsers=new ArrayList<>();
                for(Long userGroupId:userGroup){
                    CollectionNotificationRelatednessUser collectionNotificationRelatednessUser = new CollectionNotificationRelatednessUser();
                    collectionNotificationRelatednessUser.setUpdateTime(new Date());
                    collectionNotificationRelatednessUser.setCollectionNotificationUserId(userGroupId);
                    collectionNotificationRelatednessUser.setCollectionRelatednessId(collectionTask.getId());
                    collectionNotificationRelatednessUser.setRelatednessType("1");
                    collectionNotificationRelatednessUser.setUpdateUser(ShiroUtils.getUserId());
                    collectionNotificationRelatednessUser.setCreateUser(ShiroUtils.getUserId());
                    collectionNotificationRelatednessUsers.add(collectionNotificationRelatednessUser);
                }
                collectionNotificationRelatednessUserService.updateRelatednessNotification(collectionNotificationRelatednessUsers,collectionTask.getId(),"1");
            }else{
                collectionNotificationRelatednessUserService.updateRelatednessNotification(new ArrayList<>(),collectionTask.getId(),"1");
            }
        }
    }
    @Resource
    private RestHighLevelClient client;

    @Value("${elasticsearch.taskIndexName}")
    private String taskIndexName;

    @Override
    public void deleteByIds(List<Long> ids) {
        cheackIsOwnTasks(ids,ShiroUtils.getUserId());
        //删除es中对应的任务记录
        BulkRequest request = new BulkRequest();
        for (Long id : ids) {
            request.add(new DeleteRequest().index(taskIndexName).id(id.toString()));
        }
        BulkResponse delete = null;
        try {
            delete = this.client.bulk(request, RequestOptions.DEFAULT);
        } catch (IOException e) {
            e.printStackTrace();
        }
        log.info("-------"+delete.status());
        //逻辑删除任务
        baseMapper.deleteByBatch(ids);
        List<CollectionTaskLog> taskLogList = collectionTaskLogMapper.selectList(
                new QueryWrapper<CollectionTaskLog>().in("task_id", ids));
        if (CollectionUtil.isNotEmpty(taskLogList)) {
            List<Long> logIds = taskLogList.stream().map(CollectionTaskLog::getId)
                    .collect(Collectors.toList());
            //物理删除导入日志信息
            collectionTaskLogMapper.deleteBatchIdsLogic(logIds);
            //字段日志先不删除
//            List<CollectionTableFieldLog> list = collectionTableFieldLogMapper.selectList(
//                    new QueryWrapper<CollectionTableFieldLog>().in("log_id", logIds));
//            if (CollectionUtil.isNotEmpty(list)) {
//                //物理删除运行详情日志
//                List<Long> tableLogIds = list.stream().map(CollectionTableFieldLog::getId)
//                        .collect(Collectors.toList());
//                collectionTableFieldLogMapper.deleteBatchIds(tableLogIds);
//            }
        }
    }

    private void cheackIsOwnTasks(List<Long> ids, Long userId) {
        List<CollectionTask> collectionTasks = baseMapper.selectBatchIds(ids);
        if(CollectionUtil.isNotEmpty(collectionTasks)){
            for (CollectionTask collectionTask : collectionTasks) {
                if(!Objects.equals(collectionTask.getCreateUser(),userId)){
                    throw new RRException("非本人的采集任务，不能删除！");
                }
            }
        }
    }

    @Override
    public CollectionTaskDetail getDetailById(Long id) {
        CollectionTask record = baseMapper.selectById(id);
        if (record == null) {
            throw new RRException("任务不存在");
        }
        CollectionTaskDetail detail = new CollectionTaskDetail(record);
        SysUserEntity user = sysUserService.getById(detail.getUpdateUser());
        detail.setUpdateUserName(user.getRealName());
        detail.setSourceType(record.getSourceType());
        detail.setDbName(record.getDbName());

        List<CollectionSystemModuleEntity> moduleList = collectionSystemModuleService.list();
        String moduleName = ModuleUtils.getAllPath(moduleList, record.getOwnModule());
        detail.setModuleName(moduleName);
        String sourceType = ConnectTypeEnum.getTypeString(record.getSourceType());
        detail.setSourceType(sourceType);
        SysRoleEntity roleEntity = sysRoleService.getById(record.getInitRole());
        if(roleEntity != null)
            detail.setRoleName(roleEntity.getRoleName());

        if (ObjectUtils.equals(record.getTaskType(), 1)) {//0 手动采集 1自动采集
            ConfConnect confConnect = confConnectService.getById(record.getSourceId());
            if (confConnect != null){
                detail.setSourceName(confConnect.getName());
                detail.setSourceHost(confConnect.getHost());
                detail.setPort(confConnect.getPort());
                detail.setUser(confConnect.getUsername());
                //detail.setDbName(confConnect.getDbname());
            }

            CollectionTaskScheduleConfigEntity taskScheduleConfigEntity = collectionTaskScheduleConfigService.getById(id);
            if (taskScheduleConfigEntity != null){
                detail.setScheduleEnable(taskScheduleConfigEntity.getScheduleEnable());
                detail.setScheduleMode(taskScheduleConfigEntity.getScheduleMode());
                detail.setScheduleUnit(taskScheduleConfigEntity.getScheduleUnit());
                if(StringUtils.isNotEmpty(taskScheduleConfigEntity.getScheduleUnitValue())){
                    String[] split = taskScheduleConfigEntity.getScheduleUnitValue().split(" ");
                    switch (taskScheduleConfigEntity.getScheduleUnit()){
                        case 1:
                        case 2:
                            detail.setIntervalValue(Integer.parseInt(taskScheduleConfigEntity.getScheduleUnitValue()));
                            break;
                        case 3:
                            detail.setScheduleMinute(Integer.parseInt(split[0]));
                            break;
                        case 4:
                            detail.setScheduleMinute(Integer.parseInt(split[0]));
                            detail.setScheduleHour(Integer.parseInt(split[1]));
                            break;
                        case 5:
                        case 6:
                            detail.setScheduleMinute(Integer.parseInt(split[0]));
                            detail.setScheduleHour(Integer.parseInt(split[1]));
                            detail.setScheduleDay(Integer.parseInt(split[2]));
                            break;
                    }
                }
            }
        }
        detail.setCategoryIdsList(this.baseMapper.selectCategoryIdsList(id.intValue(),ShiroUtils.getTenantId()));
        return detail;
    }

    @Override
    public PageUtils selectListPage(CollectionTaskListReq req) {
        Map<String, Object> params = MapUtils.objectToMap(req);
        IPage<CollectionTask> page = this.baseMapper.selectListPage(
                (Page<CollectionTask>) new Query<CollectionTask>().getPage(params), params);
        for(CollectionTask task:page.getRecords()){
            task.setCategoryIdsList(this.baseMapper.selectCategoryIdsList(task.getId().intValue(),ShiroUtils.getTenantId()));
        }
        return new PageUtils(page);
    }


    /**
    * @Description 设置新增表的默认数据密级
    * @Author  chengweiping
    * @Date   2021/3/23 17:26
    */
    private  void setTableDefaultSecrityData(CollectionTableInfo  collectionTableInfo, SecurityLevelVO securityLevelVO){
             try{
                 if(securityLevelVO==null){
                     return;
                 }
                 //只设置新增表的数据密级
                 if(collectionTableInfo!=null&&collectionTableInfo.getId()==null){
                     collectionTableInfo.setSecurityDataLevel(securityLevelVO.getSecurityDataLevelName());
                 }
             }catch (Exception e){
                 e.printStackTrace();
             }
    }

    /**
     * @Description 设置新增表的默认数据密级和默认分区
     * @Author  chengweiping
     * @Date   2021/3/23 17:26
     */
    private  void setFieldDefaultSecrityData(List<CollectionTableField> tableFieldList, SecurityLevelVO securityLevelVO){
        try{
            if(securityLevelVO==null){
                return;
            }
            if(CollectionUtil.isEmpty(tableFieldList)){
                return ;
            }
            for(CollectionTableField tableField:tableFieldList){
                if(tableField!=null&&tableField.getIsPartition()==null){
                    //导入的字段分区没填值，则默认填0
                    tableField.setIsPartition(0);
                }
                if(tableField!=null&&tableField.getSecurityDataLevel()==null){
                    tableField.setSecurityDataLevel(securityLevelVO.getSecurityDataLevelName());
                }
            }
        }catch (Exception e){
            e.printStackTrace();
        }

    }

    /**
     *  发送邮件
     * @param tableAddList     添加表
     * @param tableUpdateList  更新表
     * @param tableDeleteList  删除表
     * @param fieldAddList     添加字段
     * @param fieldUpdateList  更新字段
     * @param fieldDeleteList  删除字段
     */
    @Transactional
    public void sendEmailFeignApi(List<CollectionTableInfo> tableAddList,List<CollectionTableInfo> tableUpdateList,
                                   List<CollectionTableInfo> tableDeleteList,List<CollectionTableField> fieldAddList,
                                   List<CollectionTableField> fieldUpdateList,List<CollectionTableField> fieldDeleteList,
                                   CollectionTask task){
        //添加字段
        ArrayList<CollectionNotificationExample> addField=new ArrayList<CollectionNotificationExample>();
        //修改字段
        ArrayList<CollectionNotificationExample> updateField=new ArrayList<CollectionNotificationExample>();
        //删除字段
        ArrayList<CollectionNotificationExample> delField=new ArrayList<CollectionNotificationExample>();
        //更新表
        ArrayList<CollectionNotificationExample> updateTable=new ArrayList<CollectionNotificationExample>();
        //删除表
        ArrayList<CollectionNotificationExample> delTable=new ArrayList<CollectionNotificationExample>();
        //添加表操作(也就是新增字段)
        if(CollectionUtil.isNotEmpty(tableAddList)){ }
        //修改表
        if(CollectionUtil.isNotEmpty(tableUpdateList)){ }
        //修改字段
        if(CollectionUtil.isNotEmpty(fieldUpdateList)){
            for(CollectionTableField collectionTableField:fieldUpdateList){
                CollectionNotificationExample collectionNotificationExample=new CollectionNotificationExample();
                //获取表信息
                CollectionTableInfo byId = collectionTableInfoService.getById(collectionTableField.getTableId());
                log.info("添加字段=="+collectionTableField.toString(),"表信息"+byId==null?byId: byId.toString());
                BeanUtils.copyProperties(byId,collectionNotificationExample);
                collectionNotificationExample.setChangeContent(collectionTableField.getChangeInfo());
                collectionNotificationExample.setChangeType("修改字段类型");
                updateField.add(collectionNotificationExample);
            }
        }
        //添加字段
        if(CollectionUtil.isNotEmpty(fieldAddList)){
          for(CollectionTableField collectionTableField:fieldAddList){
              CollectionNotificationExample collectionNotificationExample=new CollectionNotificationExample();
              //获取表信息
              CollectionTableInfo byId = collectionTableInfoService.getById(collectionTableField.getTableId());
              log.info("添加字段=="+collectionTableField.toString(),"表信息"+byId==null?byId: byId.toString());
              BeanUtils.copyProperties(byId,collectionNotificationExample);
              collectionNotificationExample.setChangeContent(collectionTableField.getFieldName()+" ("+collectionTableField.getFieldType()+")");
              collectionNotificationExample.setChangeType("新增字段");
              addField.add(collectionNotificationExample);
          }
        }
        //删除字段
        if(CollectionUtil.isNotEmpty(fieldDeleteList)){
            for(CollectionTableField collectionTableField:fieldDeleteList){
                CollectionNotificationExample collectionNotificationExample=new CollectionNotificationExample();
                //获取表信息
                CollectionTableInfo byId = collectionTableInfoService.getById(collectionTableField.getTableId());
                log.info("删除字段信息=="+collectionTableField.toString(),"表信息"+byId==null?byId: byId.toString());
                BeanUtils.copyProperties(byId,collectionNotificationExample);
                collectionNotificationExample.setChangeContent(collectionTableField.getFieldName()+" ("+collectionTableField.getFieldType()+")");
                collectionNotificationExample.setChangeType("删除字段");
                delField.add(collectionNotificationExample);
            }
        }
        //删除表
        if(CollectionUtil.isNotEmpty(tableDeleteList)){
            for(CollectionTableInfo collectionTableInfo:tableDeleteList){
                CollectionNotificationExample collectionNotificationExample=new CollectionNotificationExample();
                collectionNotificationExample.setChangeType("删除表");
                log.info("删除表==");
                BeanUtils.copyProperties(collectionTableInfo,collectionNotificationExample);
                delTable.add(collectionNotificationExample);
            }
        }
        //拼接邮件其他的参数并当历史数据保存
        UserListRes info = sysUserService.info(task.getCreateUser());
        //查询租户
        SysTenant byId1 = sysTenantService.getById(task.getTenantId());
        //拼接所有的邮箱
        StringBuffer email = new StringBuffer();
        HashMap<String,String> map = new HashMap<>();
        map.put("title",task.getTaskName());
        map.put("taskName",task.getTaskName());
        map.put("creatuser",info.getUsername()+"("+byId1.getName()+")");
        map.put("toemail",info.getEmail());
        //查询（多个用户组）
        List<CollectionNotificationUser> collectionNotificationUsers = collectionNotificationRelatednessUserService.queryNotificaCondition(task.getId(), "1");
        if(CollectionUtil.isNotEmpty(collectionNotificationUsers)){
            for(CollectionNotificationUser collectionNotificationUser:collectionNotificationUsers){
                //获取要发送的邮箱信息
                List<CollectionNotificationReceived> collectionNotificationReceiveds = collectionNotificationReceivedService.queryByNotificationUserId(collectionNotificationUser.getId());
                    //免打扰结束时间为空，或当前时间免大于免打扰结束时间，或者当前时间小于免打扰开始时间，都立刻发
                if (collectionNotificationUser.getNoDisturbingEnd() == null ||
                        (collectionNotificationUser.getNoDisturbingEnd()!=null&& LocalTime.now().compareTo(UDateToLocalTime(collectionNotificationUser.getNoDisturbingEnd()))>0) ||
                        (collectionNotificationUser.getNoDisturbingStart()!=null&&LocalTime.now().compareTo(UDateToLocalTime(collectionNotificationUser.getNoDisturbingStart()))<0) ){
                        if(CollectionUtil.isNotEmpty(collectionNotificationReceiveds)){
                            //对发送的邮箱进行去重操作
                            List<CollectionNotificationReceived> personList = new ArrayList<>();
                            collectionNotificationReceiveds.stream().filter(distinctByKey(p -> p.getEmail())).forEach(p -> personList.add(p));
                            //对告警接收人统一发送
                             for(CollectionNotificationReceived notificationReceived:personList){
                                 email.append(notificationReceived.getEmail()+",");
                             }
                             map.put("email",email.toString());
                            //发送邮件(已经去重了)
                            for(CollectionNotificationReceived collectionNotificationReceived:personList){
                                try {
                                    StringBuilder stringBuilder = TableHtmlUtil.tableToHTML(addField, updateField, delField, updateTable, delTable, map);
                                    if(stringBuilder==null){ return;}
                                    //发送邮件
                                    String content = stringBuilder.toString();
                                    sendEMailUtil.createSimpleMail(collectionNotificationReceived.getEmail(),map.get("title")+"源端元数据变更通知",content);
                                    //保存信息
                                    CollectionNotificationHistory collectionNotificationHistory = new CollectionNotificationHistory();
                                    BeanUtils.copyProperties(collectionNotificationReceived,collectionNotificationHistory);
                                    collectionNotificationHistory.setCreateTime(new Date());
                                    collectionNotificationHistory.setNotificationContent(content);
                                    collectionNotificationHistory.setNotificationTitle("元数据手动采集变更通知");
                                    collectionNotificationHistory.setNotificationTime(new Date());
                                    collectionNotificationHistory.setNotificationFlag(1);
                                    collectionNotificationHistory.setRelatednessType("1");
                                    collectionNotificationHistory.setNotificationType("1");
                                    collectionNotificationHistory.setNotificationReceivedId(task.getId());
                                    collectionNotificationHistory.setTenantId(collectionNotificationReceived.getTenantId());
                                    collectionNotificationHistory.setCreateUser(collectionNotificationReceived.getCreateUser());
                                    collectionNotificationHistoryService.saveCollectionNotificationHistory(collectionNotificationHistory);
                                } catch (Exception e) {
                                    e.printStackTrace();
                                }
                            }
                        }
                //免打扰时间  先把要发送的邮箱信息保存  随后发送出去
                }else{
                    if(CollectionUtil.isNotEmpty(collectionNotificationReceiveds)){
                        //对发送的邮箱进行去重操作
                        List<CollectionNotificationReceived> personList = new ArrayList<>();
                        collectionNotificationReceiveds.stream().filter(distinctByKey(p -> p.getEmail())).forEach(p -> personList.add(p));
                        //对告警接收人统一发送
                        for(CollectionNotificationReceived notificationReceived:personList){
                            email.append(notificationReceived.getEmail()+",");
                        }
                        map.put("email",email.toString());
                        //发送邮件(已经去重了)
                        for(CollectionNotificationReceived collectionNotificationReceived:collectionNotificationReceiveds){
                            StringBuilder stringBuilder = TableHtmlUtil.tableToHTML(addField, updateField, delField, updateTable, delTable, map);
                            if(stringBuilder==null){ return;}
                            //保存发送邮件记录
                            String content = stringBuilder.toString();
                            CollectionNotificationHistory collectionNotificationHistory = new CollectionNotificationHistory();
                            BeanUtils.copyProperties(collectionNotificationReceived,collectionNotificationHistory);
                            collectionNotificationHistory.setCreateTime(new Date());
                            collectionNotificationHistory.setNotificationContent(content);
                            collectionNotificationHistory.setNotificationTitle("元数据手动采集变更通知");
                            collectionNotificationHistory.setNotificationTime(new Date());
                            collectionNotificationHistory.setNotificationFlag(2);
                            collectionNotificationHistory.setRelatednessType("1");
                            collectionNotificationHistory.setNotificationType("1");
                            collectionNotificationHistory.setTenantId(collectionNotificationReceived.getTenantId());
                            collectionNotificationHistory.setCreateUser(collectionNotificationReceived.getCreateUser());
                            collectionNotificationHistory.setNotificationReceivedId(task.getId());
                            collectionNotificationHistoryService.saveCollectionNotificationHistory(collectionNotificationHistory);
                        }
                    }
                    SendEmailDelayUtil.addTask(collectionNotificationUser.getId(), collectionNotificationUser.getNoDisturbingEnd().getTime(),"");
                }
            }
        }
    }

    public LocalTime UDateToLocalTime(Date date) {
        Instant instant = date.toInstant();
        ZoneId zone = ZoneId.systemDefault();
        LocalDateTime localDateTime = LocalDateTime.ofInstant(instant, zone);
        LocalTime localTime = localDateTime.toLocalTime();
        return  localTime;
    }
}
